module vga(clk, rst, butU, butD, butL, butR, en, VGA_R, VGA_G, VGA_B,VGA_HS, VGA_VS,VGA_CLK,VGA_SYNC, VGA_BLANK);

input clk,rst,butU,butD,butL,butR,en;

output [7:0] VGA_R, VGA_G, VGA_B;
output VGA_BLANK, VGA_SYNC, VGA_CLK, VGA_HS, VGA_VS;

wire [31:0] pixelcount, linecount;
wire [23:0] chepos, clor;
wire Caddress, cheadd, Ciradd, C;


countadd pixelcount_address(clk, rst, pixelcount, linecount, Caddress);
cursor cursor_pos_move(clk, rst, pixelcount, linecount, butU, butD, butL, butR, Ciradd, circount, n);
chelogic checker_log(clk, rst, en, n, chepos, clor);
checkeradd checker_address(clk, rst, pixelcount, linecount, clor, chepos, cheadd);
vgadis checker_display (clk, rst, pixelcount, linecount, Caddress, Ciradd, cheadd, C, VGA_R, VGA_G, VGA_B,VGA_HS, VGA_VS,VGA_CLK,VGA_SYNC, VGA_BLANK);
ps2_decode_module keyb(clk,rst,h2l_sig,ps2_data_pin_in,ps2_data,ps2_done_sig,ps2_byte);
endmodule


module countadd(clk, rst, pixelcount, linecount, Caddress);
input clk, rst;
output [31:0] pixelcount, linecount;
output Caddress;

reg [31:0] pixelcount, linecount;
reg [2:0] Xaddress, Yaddress;

parameter left=184;
parameter top=29;
parameter width=100;
// pixel counter and line counter
always@(posedge clk or negedge rst)
begin
	if (rst==1'b0)
		begin
		pixelcount<=32'd0;
		linecount<=32'd0;
		end
		else
		if (pixelcount>32'd1040)
			begin
				pixelcount<=32'd0;
				if (linecount>32'd666)
					linecount<=32'd0;
				else
					linecount<= linecount+1;
			end
		else
			pixelcount<= pixelcount+1;


end

//row address
always@(posedge clk or negedge rst)
begin
if(!rst) Xaddress<=3'b000;
else if (pixelcount>=left && pixelcount<left+width) Xaddress<=3'b000;
else if (pixelcount>=left+width && pixelcount<left+2*width) Xaddress<=3'b001;
else if (pixelcount>=left+2*width && pixelcount<left+3*width) Xaddress<=3'b010;
else if (pixelcount>=left+3*width && pixelcount<left+4*width) Xaddress<=3'b011;
else if (pixelcount>=left+4*width && pixelcount<left+5*width) Xaddress<=3'b100;
else if (pixelcount>=left+5*width && pixelcount<left+6*width) Xaddress<=3'b101;
else if (pixelcount>=left+6*width && pixelcount<left+7*width) Xaddress<=3'b110;
else if (pixelcount>=left+7*width && pixelcount<left+8*width) Xaddress<=3'b111;
end

//colum address
always@(posedge clk or negedge rst)
begin
if(!rst) Yaddress<=3'b000;
else if (linecount>=top && linecount<top+width) Yaddress<=3'b000;
else if (linecount>=top+width && linecount<top+2*width) Yaddress<=3'b001;
else if (linecount>=top+2*width && linecount<top+3*width) Yaddress<=3'b010;
else if (linecount>=top+3*width && linecount<top+4*width) Yaddress<=3'b011;
else if (linecount>=top+4*width && linecount<top+5*width) Yaddress<=3'b100;
else if (linecount>=top+5*width && linecount<top+6*width) Yaddress<=3'b101;
end

//combine address
assign Caddress={Yaddress[0]^Xaddress[0]};
endmodule



//cursor
module cursor(clk, rst, pixelcount, linecount, butU, butD, butL, butR, Ciradd, circount, n);
input clk, rst, butU, butD, butL, butR;
input [31:0] pixelcount, linecount;
output [5:0] circount;
output Ciradd;
output n;

reg [31:0]r; //cursor
reg [5:0] circount;
reg [5:0] downcount;
reg [5:0] upcount;
reg [5:0] leftcount;
reg [5:0] rightcount;
reg Ciradd;
reg [4:0]n;
 
//cursor counter
always@(posedge butD or negedge rst)
begin
	if(!rst) downcount<=6'd0;
	else if (downcount>=6'd48)
	downcount<=6'd0;
	else if (circount==6'd4 || circount==6'd16 || circount==6'd28 || circount==6'd40 || circount==6'd47 || circount==6'd11 || circount==6'd23 || circount==6'd35)
	downcount<=downcount;
	else
	downcount<=downcount+6'b000010;
end

always@(posedge butU or negedge rst)
begin
	if(!rst) upcount<=6'd0;
	else if (upcount>=6'd48)
	upcount<=6'd0;
	else if (circount==6'd0 || circount==6'd12 || circount==6'd24 || circount==6'd36 || circount==6'd7 || circount==6'd19 || circount==6'd31 || circount==6'd43)
	upcount<=upcount;
	else
	upcount<=upcount+6'b000010;
end

always@(posedge butR or negedge rst)
begin
	if(!rst) rightcount<=6'd0;
	else if (rightcount>=6'd48)
	rightcount<=6'd0;
	else if (circount==6'd43 || circount==6'd45 || circount==6'd47)
	rightcount<=rightcount;
	else if (circount[0]==1'b0)
	rightcount<=rightcount+6'b000111;
	else if (circount[0]==1'b1)
	rightcount<=rightcount+6'b000101;
end

always@(posedge butL or negedge rst)
begin
	if(!rst) leftcount<=6'd0;
	else if (leftcount>=6'd48)
	leftcount<=6'd0;
	else if (circount==6'd0 || circount==6'd2 || circount==6'd4)
	leftcount<=leftcount;
	else if (circount[0]==1'b0)
	leftcount<=leftcount+6'b000101;
	else if (circount[0]==1'b1)
	leftcount<=leftcount+6'b000111;
end

always@(posedge clk or negedge rst)
begin
	if(!rst) circount<=6'd0;
	else if (circount>=6'd48)
	begin
	circount<=6'd0;
	end
	else
	circount<=downcount-upcount+rightcount-leftcount;
end


//circle cursor
always@(posedge clk or negedge rst)
begin
if (!rst) r<=32'd0;
else
	begin
	case(circount)
	6'b000000:
	begin
		n<=5'b00000;
		if (pixelcount>=184 && pixelcount<284 && linecount>=29 && linecount<=129)
		r<=(233-pixelcount)*(233-pixelcount)+(78-linecount)*(78-linecount);
		else
		r<=3000;
	end
	
	6'b000010:
	begin
		n<=5'b00001;
		if (pixelcount>=184 && pixelcount<284 && linecount>=229 && linecount<=329)
		r<=(233-pixelcount)*(233-pixelcount)+(278-linecount)*(278-linecount);
		else
		r<=3000;
	end
	
	6'b000100:
	begin
		n<=5'b00010;
		if (pixelcount>=184 && pixelcount<284 && linecount>=429 && linecount<=529)
		r<=(233-pixelcount)*(233-pixelcount)+(478-linecount)*(478-linecount);
		else
		r<=3000;
	end
	
	////////////////////////////////////
	6'b000111:
	begin
		n<=5'b00011;
		if (pixelcount>=284 && pixelcount<384 && linecount>=129 && linecount<=229)
		r<=(333-pixelcount)*(333-pixelcount)+(178-linecount)*(178-linecount);
		else
		r<=3000;
	end
	
	6'b001001:
	begin
		n<=5'b00100;
		if (pixelcount>=284 && pixelcount<=384 && linecount>=329 && linecount<=429)
		r<=(333-pixelcount)*(333-pixelcount)+(378-linecount)*(378-linecount);
		else
		r<=3000;
	end
	
	6'b001011:
	begin
		n<=5'b00101;
		if (pixelcount>=284 && pixelcount<=384 && linecount>=529 && linecount<=629)
		r<=(333-pixelcount)*(333-pixelcount)+(578-linecount)*(578-linecount);
		else
		r<=3000;
	end
	
	//////////////////////////////////////
	6'b001100:
	begin
		n<=5'b00110;
		if (pixelcount>=384 && pixelcount<=484 && linecount>=29 && linecount<=129)
		r<=(433-pixelcount)*(433-pixelcount)+(78-linecount)*(78-linecount);
		else
		r<=3000;
	end
	
	6'b001110:
	begin
		n<=5'b00111;
		if (pixelcount>=384 && pixelcount<=484 && linecount>=229 && linecount<=329)
		r<=(433-pixelcount)*(433-pixelcount)+(278-linecount)*(278-linecount);
		else
		r<=3000;
	end
	
	6'b010000:
	begin
		n<=5'b01000;
		if (pixelcount>=384 && pixelcount<=484 && linecount>=429 && linecount<=529)
		r<=(433-pixelcount)*(433-pixelcount)+(478-linecount)*(478-linecount);
		else
		r<=3000;
	end
	
	/////////////////////////////////////
	6'b010011:
	begin
		n<=5'b01001;
		if (pixelcount>=484 && pixelcount<=584 && linecount>=129 && linecount<=229)
		r<=(533-pixelcount)*(533-pixelcount)+(178-linecount)*(178-linecount);
		else
		r<=3000;
	end
	
	6'b010101:
	begin
		n<=5'b01010;
		if (pixelcount>=484 && pixelcount<=584 && linecount>=329 && linecount<=429)
		r<=(533-pixelcount)*(533-pixelcount)+(378-linecount)*(378-linecount);
		else
		r<=3000;
	end
	
	6'b010111:
	begin
		n<=5'b01011;
		if (pixelcount>=484 && pixelcount<=584 && linecount>=529 && linecount<=629)
		r<=(533-pixelcount)*(533-pixelcount)+(578-linecount)*(578-linecount);
		else
		r<=3000;
	end
	
	/////////////////////////////////////
	6'b011000:
	begin
		n<=5'b01100;
		if (pixelcount>=584 && pixelcount<=684 && linecount>=29 && linecount<=129)
		r<=(633-pixelcount)*(633-pixelcount)+(78-linecount)*(78-linecount);
		else
		r<=3000;
	end
	
	6'b011010:
	begin
		n<=5'b01101;
		if (pixelcount>=584 && pixelcount<=684 && linecount>=229 && linecount<=329)
		r<=(633-pixelcount)*(633-pixelcount)+(278-linecount)*(278-linecount);
		else
		r<=3000;
	end
	
	6'b011100:
	begin
		n<=5'b01110;
		if (pixelcount>=584 && pixelcount<=684 && linecount>=429 && linecount<=529)
		r<=(633-pixelcount)*(633-pixelcount)+(478-linecount)*(478-linecount);
		else
		r<=3000;
	end
	
	/////////////////////////////////////
	6'b011111:
	begin
		n<=5'b01111;
		if (pixelcount>=684 && pixelcount<=784 && linecount>=129 && linecount<=229)
		r<=(733-pixelcount)*(733-pixelcount)+(178-linecount)*(178-linecount);
		else
		r<=3000;
	end
	
	6'b100001:
	begin
		n<=5'b10000;
		if (pixelcount>=684 && pixelcount<=784 && linecount>=329 && linecount<=429)
		r<=(733-pixelcount)*(733-pixelcount)+(378-linecount)*(378-linecount);
		else
		r<=3000;
	end
	
	6'b100011:
	begin
		n<=5'b10001;
		if (pixelcount>=684 && pixelcount<=784 && linecount>=529 && linecount<=629)
		r<=(733-pixelcount)*(733-pixelcount)+(578-linecount)*(578-linecount);
		else
		r<=3000;
	end
	
	////////////////////////////////////
	6'b100100:
	begin
		n<=5'b10010;
		if (pixelcount>=784 && pixelcount<=884 && linecount>=29 && linecount<=129)
		r<=(833-pixelcount)*(833-pixelcount)+(78-linecount)*(78-linecount);
		else
		r<=3000;
	end
	
	6'b100110:
	begin
		n<=5'b10011;
		if (pixelcount>=784 && pixelcount<=884 && linecount>=229 && linecount<=329)
		r<=(833-pixelcount)*(833-pixelcount)+(278-linecount)*(278-linecount);
		else
		r<=3000;
	end
	
	6'b101000:
	begin
		n<=5'b10100;
		if (pixelcount>=784 && pixelcount<=884 && linecount>=429 && linecount<=529)
		r<=(833-pixelcount)*(833-pixelcount)+(478-linecount)*(478-linecount);
		else
		r<=3000;
	end
	
	///////////////////////////////////
	6'b101011:
	begin
		n<=5'b10101;
		if (pixelcount>=884 && pixelcount<=984 && linecount>=129 && linecount<=229)
		r<=(933-pixelcount)*(933-pixelcount)+(178-linecount)*(178-linecount);
		else
		r<=3000;
	end
	
	6'b101101:
	begin
		n<=5'b10110;
		if (pixelcount>=884 && pixelcount<=984 && linecount>=329 && linecount<=429)
		r<=(933-pixelcount)*(933-pixelcount)+(378-linecount)*(378-linecount);
		else
		r<=3000;
	end
	
	6'b101111:
	begin
		n<=5'b10111;
		if (pixelcount>=884 && pixelcount<=984 && linecount>=529 && linecount<=629)
		r<=(933-pixelcount)*(933-pixelcount)+(578-linecount)*(578-linecount);
		else
		r<=3000;
	end
	default: r<=12'd0;
	endcase
	end
end

always@(posedge clk or negedge rst)
begin
if (!rst) Ciradd<=1'b0;
else if (r>1500) Ciradd<=1'b0;
else Ciradd<=1'b1;
end
endmodule


//checker position address
module checkeradd(clk, rst, pixelcount, linecount, chepos, clor, cheadd, C);
input clk, rst;
input [31:0]pixelcount, linecount;
input [23:0]chepos;
input [23:0]clor;
output cheadd;
output C;

reg [31:0] R;
reg C; //checker
reg [1:0]cheadd;

always@(posedge clk or negedge rst)
begin
if(!rst) R<=0;
else if (pixelcount>=184 && pixelcount<284 && linecount>=29 && linecount<129)
		begin
		R<=(233-pixelcount*chepos[0])*(233-pixelcount*chepos[0])+(78-linecount*chepos[0])*(78-linecount*chepos[0]);
		C<=clor[0];
		end
else if (pixelcount>=384 && pixelcount<484 && linecount>=29 && linecount<129)
		begin
		R<=(433-pixelcount*chepos[6])*(433-pixelcount*chepos[6])+(78-linecount*chepos[6])*(78-linecount*chepos[6]);
		C<=clor[6];
		end
else if (pixelcount>=584 && pixelcount<684 && linecount>=29 && linecount<129)
		begin
		R<=(633-pixelcount*chepos[12])*(633-pixelcount*chepos[12])+(78-linecount*chepos[12])*(78-linecount*chepos[12]);
		C<=clor[12];
		end
else if (pixelcount>=784 && pixelcount<884 && linecount>=29 && linecount<129)
		begin
		R<=(833-pixelcount*chepos[18])*(833-pixelcount*chepos[18])+(78-linecount*chepos[18])*(78-linecount*chepos[18]);
		C<=clor[18];
		end
		
else if (pixelcount>=284 && pixelcount<384 && linecount>=129 && linecount<229)
		begin
		R<=(333-pixelcount*chepos[3])*(333-pixelcount*chepos[3])+(178-linecount*chepos[3])*(178-linecount*chepos[3]);
		C<=clor[3];
		end
else if (pixelcount>=484 && pixelcount<584 && linecount>=129 && linecount<229)
		begin
		R<=(533-pixelcount*chepos[9])*(533-pixelcount*chepos[9])+(178-linecount*chepos[9])*(178-linecount*chepos[9]);
		C<=clor[9];
		end
else if (pixelcount>=684 && pixelcount<784 && linecount>=129 && linecount<229)
		begin
		R<=(733-pixelcount*chepos[15])*(733-pixelcount*chepos[15])+(178-linecount*chepos[15])*(178-linecount*chepos[15]);
		C<=clor[15];
		end
else if (pixelcount>=884 && pixelcount<984 && linecount>=129 && linecount<229)
		begin
		R<=(933-pixelcount*chepos[21])*(933-pixelcount*chepos[21])+(178-linecount*chepos[21])*(178-linecount*chepos[21]);
		C<=clor[21];
		end

else if (pixelcount>=184 && pixelcount<284 && linecount>=229 && linecount<329)
		begin
		R<=(233-pixelcount*chepos[1])*(233-pixelcount*chepos[1])+(278-linecount*chepos[1])*(278-linecount*chepos[1]);
		C<=clor[1];
		end
else if (pixelcount>=384 && pixelcount<484 && linecount>=229 && linecount<329)
		begin
		R<=(433-pixelcount*chepos[7])*(433-pixelcount*chepos[7])+(278-linecount*chepos[7])*(278-linecount*chepos[7]);
		C<=clor[7];
		end
else if (pixelcount>=584 && pixelcount<684 && linecount>=229 && linecount<329)
		begin
		R<=(633-pixelcount*chepos[13])*(633-pixelcount*chepos[13])+(278-linecount*chepos[13])*(278-linecount*chepos[13]);
		C<=R*clor[13];
		end
else if (pixelcount>=784 && pixelcount<884 && linecount>=229 && linecount<329)
		begin
		R<=(833-pixelcount*chepos[19])*(833-pixelcount*chepos[19])+(278-linecount*chepos[19])*(278-linecount*chepos[19]);
		C<=clor[19];
		end
		
else if (pixelcount>=284 && pixelcount<384 && linecount>=329 && linecount<429)
		begin
		R<=(333-pixelcount*chepos[4])*(333-pixelcount*chepos[4])+(378-linecount*chepos[4])*(378-linecount*chepos[4]);
		C<=clor[4];
		end
else if (pixelcount>=484 && pixelcount<584 && linecount>=329 && linecount<429)
		begin
		R<=(533-pixelcount*chepos[10])*(533-pixelcount*chepos[10])+(378-linecount*chepos[10])*(378-linecount*chepos[10]);
		C<=clor[10];
		end
else if (pixelcount>=684 && pixelcount<784 && linecount>=329 && linecount<429)
		begin
		R<=(733-pixelcount*chepos[16])*(733-pixelcount*chepos[16])+(378-linecount*chepos[16])*(378-linecount*chepos[16]);
		C<=clor[16];
		end
else if (pixelcount>=884 && pixelcount<984 && linecount>=329 && linecount<429)
		begin
		R<=(933-pixelcount*chepos[22])*(933-pixelcount*chepos[22])+(378-linecount*chepos[22])*(378-linecount*chepos[22]);
		C<=clor[22];
		end		

else if (pixelcount>=184 && pixelcount<284 && linecount>=429 && linecount<529)
		begin
		R<=(233-pixelcount*chepos[2])*(233-pixelcount*chepos[2])+(478-linecount*chepos[2])*(478-linecount*chepos[2]);
		C<=clor[2];
		end
else if (pixelcount>=384 && pixelcount<484 && linecount>=429 && linecount<529)
		begin
		R<=(433-pixelcount*chepos[8])*(433-pixelcount*chepos[8])+(478-linecount*chepos[8])*(478-linecount*chepos[8]);
		C<=clor[8];
		end
else if (pixelcount>=584 && pixelcount<684 && linecount>=429 && linecount<529)
		begin
		R<=(633-pixelcount*chepos[14])*(633-pixelcount*chepos[14])+(478-linecount*chepos[14])*(478-linecount*chepos[14]);
		C<=clor[14];
		end
else if (pixelcount>=784 && pixelcount<884 && linecount>=429 && linecount<529)
		begin
		R<=(833-pixelcount*chepos[20])*(833-pixelcount*chepos[20])+(478-linecount*chepos[20])*(478-linecount*chepos[20]);
		C<=clor[20];
		end
		
else if (pixelcount>=284 && pixelcount<384 && linecount>=529 && linecount<629)
		begin
		R<=(333-pixelcount*chepos[5])*(333-pixelcount*chepos[5])+(578-linecount*chepos[5])*(578-linecount*chepos[5]);
		C<=clor[5];
		end
else if (pixelcount>=484 && pixelcount<584 && linecount>=529 && linecount<629)
		begin
		R<=(533-pixelcount*chepos[11])*(533-pixelcount*chepos[11])+(578-linecount*chepos[11])*(578-linecount*chepos[11]);
		C<=clor[11];
		end
else if (pixelcount>=684 && pixelcount<784 && linecount>=529 && linecount<629)
		begin
		R<=(733-pixelcount*chepos[17])*(733-pixelcount*chepos[17])+(578-linecount*chepos[17])*(578-linecount*chepos[17]);
		C<=clor[17];
		end
else if (pixelcount>=884 && pixelcount<984 && linecount>=529 && linecount<629)
		begin
		R<=(933-pixelcount*chepos[23])*(933-pixelcount*chepos[23])+(578-linecount*chepos[23])*(578-linecount*chepos[23]);
		C<=clor[23];
		end
else
	R<=5000;
end

///cursor address
always@(posedge clk or negedge rst)
begin
if (!rst) cheadd<=1'b0;
else if (R>2000) cheadd<=1'b0;
else cheadd<=1'b1;
end
endmodule



module chelogic(clk, rst, en, n, chepos, clor);
input clk, rst, en;
input [4:0]n;
output [23:0]chepos;
output [23:0]clor;

reg [23:0]clor;
reg [23:0]chepos;
reg [3:0]S;
reg [3:0]NS;

wire remclor;

integer ufpo, dfpo, uffpo, dffpo;

parameter start=4'b000;
parameter pochos=4'b0001;
parameter check_one=4'b0010;
parameter check_two=4'b0011;
parameter poconfirm=4'b0100;
parameter poposis=4'b0101;
parameter desconfirm=4'b0110;
parameter ptchos=4'b0111;
parameter check_thr=4'b1000;
parameter check_fou=4'b1001;
parameter ptconfirm=4'b1010;
parameter ptposis=4'b1011;
parameter secdesconfirm=4'b1100;


//state converter
always@(posedge clk or negedge rst)
begin
	if (!rst) S<=4'd0;
	else S<=NS;
end


//state statement
assign perm=(chepos[ufpo] | chepos[dfpo]);
assign jump=(chepos[uffpo] & chepos[dffpo]);
assign remclor=clor[n];

always@(posedge en)
begin
case (S)
start:
	begin
		if(en==1'b1)
			begin
				NS=pochos;
			end
		else
			begin
				NS=start;
			end
	end
	
pochos:
	begin
		if (en==1'b0)
			begin
				NS=pochos;
			end
		else
			begin
				if(chepos[n]==1'b0)
					begin
						NS=pochos;
					end
				else
					begin
						if (n==5'd0 || n==5'd1 || n==5'd2 || n==5'd6 || n==5'd7 || n==5'd8 || n==5'd12 || n==5'd13 || n==5'd14 || n==5'd18 || n==5'd19 || n==5'd20)
							begin
								ufpo=n+5'd2;
								dfpo=n+5'd3;
								NS=check_one;
							end
						else
							begin
								ufpo=n+5'd3;
								dfpo=n+5'd4;
								NS=check_one;
							end
					end
			end
	end
	
check_one:
	begin
		if (perm==1'b0)
			begin
				NS=poconfirm;
			end
		else 
			begin
				if (chepos[ufpo]==1'b1)
					begin
						if (ufpo==5'd0 || ufpo==5'd1 || ufpo==5'd2 || ufpo==5'd6 || ufpo==5'd7 || ufpo==5'd8 || ufpo==5'd12 || ufpo==5'd13 || ufpo==5'd14 || ufpo==5'd18 || ufpo==5'd19 || ufpo==5'd20)
							begin
								uffpo=ufpo+5'd2;
								NS=check_two;
							end
						else
							begin
								uffpo=ufpo+5'd3;
								NS=check_two;
							end
					end
				else if (chepos[dfpo]==1'b1)
					begin
						if (dfpo==5'd0 || dfpo==5'd1 || dfpo==5'd2 || dfpo==5'd6 || dfpo==5'd7 || dfpo==5'd8 || dfpo==5'd12 || dfpo==5'd13 || dfpo==5'd14 || dfpo==5'd18 || dfpo==5'd19 || dfpo==5'd20)
							begin
								dffpo=dfpo+5'd3;
								NS=check_two;
							end
						else
							begin
								dffpo=dfpo+5'd4;
								NS=check_two;
							end
					end
			end
	end

check_two:
	begin
		if (jump==1'b1)
			begin
				NS=pochos;
			end
		else
			if(chepos[uffpo]==1'b0 || chepos[dffpo]==1'b0)
				begin
					NS=poconfirm;
				end
	end
	
poconfirm:
	begin
		NS=poposis;
	end
	
poposis:
	begin
		if(en==1'b0)
			begin
				NS=poposis;
			end
		else
			begin
				if (n==ufpo ||n==uffpo ||n==dfpo ||n==dffpo)
					begin
						NS=desconfirm;
					end
				else
					begin
						NS=poposis;
					end
			end
	end
	
desconfirm:
	begin
		NS=ptchos;
	end
	
ptchos:
	begin
		if (en==1'b0)
			begin
				NS=ptchos;
			end
		else
			begin
				if(chepos[n]==1'b0)
					begin
						NS=ptchos;
					end
				else
					begin
						if (n==5'd0 || n==5'd1 || n==5'd2 || n==5'd6 || n==5'd7 || n==5'd8 || n==5'd12 || n==5'd13 || n==5'd14 || n==5'd18 || n==5'd19 || n==5'd20)
							begin
								ufpo=n-5'd4;
								dfpo=n-5'd3;
								NS=check_thr;
							end
						else
							begin
								ufpo=n-5'd3;
								dfpo=n-5'd2;
								NS=check_thr;
							end
					end
			end
	end
	
check_thr:
	begin
		if (perm==1'b0)
			begin
				NS=ptconfirm;
			end
		else 
			begin
				if (clor[ufpo]==1'b1)
					begin
						if (ufpo==5'd0 || ufpo==5'd1 || ufpo==5'd2 || ufpo==5'd6 || ufpo==5'd7 || ufpo==5'd8 || ufpo==5'd12 || ufpo==5'd13 || ufpo==5'd14 || ufpo==5'd18 || ufpo==5'd19 || ufpo==5'd20)
							begin
								uffpo=ufpo+5'd2;
								NS=check_fou;
							end
						else
							begin
								uffpo=ufpo+5'd3;
								NS=check_fou;
							end
					end
				else if (chepos[dfpo]==1'b1)
					begin
						if (dfpo==5'd0 || dfpo==5'd1 || dfpo==5'd2 || dfpo==5'd6 || dfpo==5'd7 || dfpo==5'd8 || dfpo==5'd12 || dfpo==5'd13 || dfpo==5'd14 || dfpo==5'd18 || dfpo==5'd19 || dfpo==5'd20)
							begin
								dffpo=dfpo+5'd3;
								NS=check_fou;
							end
						else
							begin
								dffpo=dfpo+5'd4;
								NS=check_fou;
							end
					end
			end
	end

check_fou:
	begin
		if (jump==1'b1)
			begin
				NS=ptchos;
			end
		else
			if(chepos[uffpo]==1'b0 || chepos[dffpo]==1'b0)
				begin
					NS=ptconfirm;
				end
	end

ptconfirm:
	begin
		NS=ptposis;
	end

ptposis:
	begin
		if(en==1'b0)
			begin
				NS=ptposis;
			end
		else
			begin
				if (n==ufpo ||n==uffpo ||n==dfpo ||n==dffpo)
					begin
						NS=secdesconfirm;
					end
				else
					begin
						NS=ptposis;
					end
			end
	end
	
secdesconfirm:
	begin
		NS=pochos;
	end
endcase
end

always@(posedge clk or negedge rst)
begin
case(S)
start:
	begin
	chepos<=24'hFF81FF;
	clor<=24'hFF8;
	end
poconfirm:
	begin
	chepos[n]<=1'b0;
	clor[n]<=1'b0;
	end
desconfirm:
	begin
	chepos[n]<=1'b1;
	clor[n]<=1'b1;
	end
ptconfirm:
	begin
	chepos[n]<=1'b0;
	clor[n]<=1'b0;
	end
secdesconfirm:
	begin
	chepos[n]<=1'b1;
	clor[n]<=1'b1;
	end
default: 
	begin
	chepos[n]<=chepos[n];
	clor[n]<=clor[n];
	end
endcase
end

endmodule



//vga display
module vgadis(clk, rst, pixelcount, linecount, Caddress, Ciradd, C, cheadd, VGA_R, VGA_G, VGA_B,VGA_HS, VGA_VS,VGA_CLK,VGA_SYNC, VGA_BLANK);
input clk, rst, Caddress, Ciradd;
input cheadd, C;
input [31:0]pixelcount, linecount;
output [7:0] VGA_R, VGA_G, VGA_B;
output VGA_BLANK, VGA_SYNC, VGA_CLK, VGA_HS, VGA_VS;

reg [7:0] VGA_R, VGA_G, VGA_B;
reg  VGA_HS, VGA_VS, h_blank, v_blank;

wire VGA_BLANK, VGA_SYNC, valid;
// influences green only, may not be needed
assign VGA_SYNC = 0;
assign VGA_BLANK = h_blank || v_blank;
assign VGA_CLK = clk;
assign valid=((pixelcount>=32'd184)&&(pixelcount<32'd984));
//horizontal outputs
always@(posedge clk or negedge rst)
begin
	if (rst == 1'b0)
		begin 
		VGA_HS<=1'b0;
		h_blank<=1'b1;
		end
	else
	
	begin
	
	
	//HSYNC
	if (pixelcount<32'd120)
		VGA_HS<=1'b0;
	else
		VGA_HS<=1'b1;
	
	//Back porch and Front porch
	if ((pixelcount>=32'd120 && pixelcount<32'd184)|| (pixelcount>=32'd984))
		h_blank<=1'b0;
	else
		h_blank<=1'b1;
	
	
	// horizontal visible area
	
	if (valid)
		begin
			if (Caddress)
				begin
				VGA_R<=8'hB8;
				VGA_G<=8'h86;
				VGA_B<=8'h0B;
				end
			else
				begin
				if (Ciradd)
						begin
						VGA_R<=8'hFF;
			         VGA_G<=8'h00;
						VGA_B<=8'h00;
						end
				else 
					if (cheadd)
						begin
						//draw the circle
						VGA_R<=8'h18;
			         VGA_G<=8'h3C;
						VGA_B<=8'h00;
						end
					else 
						if (C)
							begin
							VGA_R<=8'h00;
							VGA_G<=8'h00;
							VGA_B<=8'h00;
							end
						else
							begin
							//remain the color
							VGA_R<=8'hF0;
							VGA_G<=8'hE6;
							VGA_B<=8'h8C;
							end
						end
		end
	else
			begin
			//dont read frame buffer
			//included to remove infered latch
			VGA_R<=8'hB8;
			VGA_G<=8'h86;
			VGA_B<=8'h0B;
		   end
	end// end else rst
end//always



// vertical outputs
always@(posedge clk or negedge rst)
begin 
	if (rst ==1'b0)
		begin
		VGA_VS<=1'b0;
		v_blank <= 1'b0;
		end
	else
	
	begin
	
	//vsync
	if (linecount<6)
		VGA_VS<=1'b0;
	else
		VGA_VS <= 1'b1;
	
	// Back porch or front porch
	if ((linecount >=6 && linecount<29)|| linecount>=629)
		v_blank<=1'b1;
	else
		v_blank <= 1'b0;
	
	//vertical visible area
		// nothing else needs to be done
		//linecount >= 32'd29 && linecount< 32'd629
		
	end// end rst else

end

endmodule

module keyboard (clk,rst,ps2_clk_pin_in,ps2_data_pin_in,ps2_data,ps2_done_sig,ps2_byte);
input clk,rst,ps2_clk_pin_in,ps2_data_pin_in;
output [7:0]ps2_data;
output [7:0]ps2_byte;
output ps2_done_sig;

wire h2l_sig;

detect_module detect (clk,rst,ps2_clk_pin_in,h2l_sig);
ps2_decode_module decode(clk,rst,h2l_sig,ps2_data_pin_in,ps2_data,ps2_done_sig,ps2_byte);

endmodule

module detect_module(clk,rst,ps2_clk_pin_in,h2l_sig);
input clk,rst,ps2_clk_pin_in;
output h2l_sig;

reg h2l_f1;
reg h2l_f2;

always @(posedge clk or negedge rst )
begin
	if (rst==1'b0)
		begin
			h2l_f1<=1'b1;
			h2l_f2<=1'b1;
		end
	else
		begin
			h2l_f1<=ps2_clk_pin_in;
			h2l_f2<=h2l_f1;
		end
end

assign h2l_sig=h2l_f2&(~h2l_f1);

endmodule

module ps2_decode_module(clk,rst,h2l_sig,ps2_data_pin_in,ps2_data,ps2_done_sig,ps2_byte);
input clk,rst,h2l_sig,ps2_data_pin_in;
output [7:0]ps2_data;
output [7:0]ps2_byte;
output ps2_done_sig;

reg [7:0]rdata;
reg[4:0]i;
reg isshife;
reg isdone;

always @(posedge clk or negedge rst)
begin
	if(rst==1'b0)
		begin
			rdata<=8'd0;
			i<=5'd0;
			isdone<=1'b0;
		end
	else
	begin
		case(i)
		5'd0:
		begin
			if(h2l_sig==1'b1) i<=i+1'b1;
		end
		5'd1,5'd2,5'd3,5'd4,5'd5,5'd6,5'd7,5'd8:
		begin
			if(h2l_sig==1'b1) begin i<=i+1'b1;rdata[i-1'b1]<=ps2_data_pin_in;end
		end
		5'd9,5'd10:
		begin
			if(h2l_sig==1'b1)i<=i+1'b1;
		end
		5'd11://break or make
		begin
			if(rdata==8'hf0)i<=5'd12;
			else i<=5'd23;
		end
		//brak until i=22
      5'd12,5'd13,5'd14,5'd15,5'd16,5'd17,5'd18,5'd19,5'd20,5'd21,5'd22:
		begin
			i<=i+1'b1;
		end
		//make
		5'd23:
		begin 
			i<=i+1'b1; isdone<=1'b1;
		end
		5'd24:
		begin
			i<=5'd0;isdone<=1'b0;
		end
      endcase
	end
	
	
end
	
assign ps2_data=rdata;
assign ps2_done_sig=isdone;

reg[7:0] ps2_asci;   

always @ (posedge clk)
 begin

    case (ps2_data)    

       8'h15: ps2_asci <= 8'h51;   //Q

       8'h1d: ps2_asci <= 8'h57;   //W

       8'h24: ps2_asci <= 8'h45;   //E

       8'h2d: ps2_asci <= 8'h52;   //R

       8'h2c: ps2_asci <= 8'h54;   //T

       8'h35: ps2_asci <= 8'h59;   //Y

       8'h3c: ps2_asci <= 8'h55;   //U

       8'h43: ps2_asci <= 8'h49;   //I

       8'h44: ps2_asci <= 8'h4f;   //O

       8'h4d: ps2_asci <= 8'h50;   //P              

       8'h1c: ps2_asci <= 8'h41;   //A

       8'h1b: ps2_asci <= 8'h53;   //S

       8'h23: ps2_asci <= 8'h44;   //D

       8'h2b: ps2_asci <= 8'h46;   //F

       8'h34: ps2_asci <= 8'h47;   //G

       8'h33: ps2_asci <= 8'h48;   //H

       8'h3b: ps2_asci <= 8'h4a;   //J

       8'h42: ps2_asci <= 8'h4b;   //K

       8'h4b: ps2_asci <= 8'h4c;   //L

       8'h1a: ps2_asci <= 8'h5a;   //Z

       8'h22: ps2_asci <= 8'h58;   //X

       8'h21: ps2_asci <= 8'h43;   //C

       8'h2a: ps2_asci <= 8'h56;   //V

       8'h32: ps2_asci <= 8'h42;   //B

       8'h31: ps2_asci <= 8'h4e;   //N

       8'h3a: ps2_asci <= 8'h4d;   //M

       default: ;

       endcase

end

assign ps2_byte = ps2_asci;

endmodule